<template>
	<view class="chat">
		<view class="chat-main">
			<scroll-view class="scroll" :style="'height: '+chatViewHeight+'px;'" :scroll-into-view="intoView"
				scroll-top="9999" :scroll-y="true" :scroll-with-animation="false" :scroll-anchoring="true"
				:upper-threshold="50" @scrolltoupper="scrollToUpper" @click.stop.prevent="onClickScroll">
				<uni-load-more :status="status" :content-text="contentText" />
				<view class="chat-detail" v-for="(item, index) in msgList" :key="item.id" :id="'chatId_' + item.id">
					<view v-if="msgTime[item.id] !== 0" class="time">
						<text
							style="text-align: center;line-height: 1;font-size: 12px;color: #888888;">{{msgTime[item.id]}}</text>
					</view>
					<view class="text-msg" :class="{'my': item.send == contacts.userId}">
						<view class="chat-detail__asdie">
							<u-avatar :src="avatarMap[item.send]" shape="square" default-url="/statice/img/default.png"
								@click.stop.prevent="toUserInfo(item.send)">
							</u-avatar>
						</view>
						<view class="chat-detail__main" :id="'msg_' + item.id">
							<text class="chat-detail__main-name" :class="{'align-end': item.send == contacts.userId}"
								v-if="item.send !== contacts.userId">{{nameMap[item.send]}}</text>
							<view class="chat-detail__main-info" :id="'w_' + item.id"
								@longpress.stop.prevent="msgLongPress(item)">
								<rich-text class="rich" :selectable="true" :nodes="item.info">
								</rich-text>
							</view>
						</view>
						<view class="chat-detail__asdie"></view>
					</view>
				</view>
			</scroll-view>
		</view>












		<view class="foot" id="foot" ref="foot">
			<view class="foot__content">
				<!--切换按钮-->
				<view class="foot__content-left">
					<image v-if="!showVoice" class="icon_img" src="@/static/img/chat/voice.png" @click="onShowVoice">
					</image>
					<image v-else class="icon_img" src="@/static/img/chat/keyboard.png" @click="onShowVoice"></image>
				</view>
				<!--文本框-->
				<view class="foot__content-center" :style="comEditorWidth">
					<view class="textArea-box" v-show="!showVoice">
						<scroll-view :scroll-y="true" class="inputScroll">
							<editor id="editor" class="ql-container" @ready="onEditorReady" @focus="onEditorFocus"
								@input="onEditorInput" @statuschange="onStatusChange">
							</editor>
						</scroll-view>
					</view>
					<view class="voice_title" v-show="showVoice">
						<text class="voice-nv">{{voiceTis}}</text>
					</view>
				</view>
				<!--功能区-->
				
				
				
				
				
				
				
				<view class="foot__content-right">
					<!--切换按钮-->
					<view style="margin-right: 20rpx;">
						<image v-if="!showEmoji" class="icon_img" src="@/static/img/chat/bq.png" @click="onShowEmoji">
						</image>
						<image v-else class="icon_img" src="@/static/img/chat/keyboard.png" @click="onShowEmoji">
						</image>
					</view>
					<!--切换按钮-->
					<view>
						<image v-if="showVoice || !isMsg" class="icon_img" src="@/static/img/chat/more.png"
							@click="onShowMore">
						</image>
						<view v-else class="send">
							<button type="primary" size="mini" @click="onSendMsg">
								<text>发送</text>
							</button>
						</view>
					</view>
				</view>
			</view>
			<!--表情-->
			<view class="fun-box">
				<emoji v-show="showEmoji" @onEmoji="onEmoji"></emoji>
			</view>
			<!--功能-->
			<view class="fun-box">
				<more-function v-show="showMore"></more-function>
			</view>
		</view>
	</view>
</template>










<script setup>
	import {
		ref,
		reactive,
		computed,
		watch,
		nextTick,
	} from 'vue';
	import {
		onNavigationBarButtonTap,
		onLoad,
		onShow,
		onReady,
		onUnload,
		onBackPress,
	} from '@dcloudio/uni-app';
	import {
		useChatStore,
	} from '@/stores/chat';
	import {
		useContactsStore,
	} from '@/stores/contacts';
	import {
		useSocketStore,
	} from '@/stores/socket';
	import {
		useUserStore,
	} from '@/stores/user'
	import {
		storeToRefs,
	} from 'pinia';
	import {
		throttle,
	} from "@/utils/index";
	import {
		dayjs,
	} from '@/utils/dayjs';

	const contacts = useContactsStore();
	const socket = useSocketStore();
	const chat = useChatStore();
	const user = useUserStore();
	let {
		msgMap,
		emojiType,
		chatList,
	} = storeToRefs(chat);

	let msg = reactive({
		text: '',
		html: '',
		delta: null,
	});
	let isMsg = ref(false);
	let showVoice = ref(false);
	let voiceTis = ref('按住 说话')
	let showMore = ref(false);
	let showEmoji = ref(false);
	let systemInfo = uni.getSystemInfoSync();
	let chatViewHeight = ref(systemInfo.safeArea.height);
	let keyBoardHeight = ref(0);
	let editorWidth = ref(0);
	let status = ref('more');
	let contentText = ref({
		contentdown: ' ',
		contentrefresh: ' ',
		contentnomore: ' ',
	});
	let intoView = ref('');

	let editorCtx = ref(null);

	let id = ref(-1);
	let type = ref('friend');
	let back = ref(undefined);
	let info = ref(null);
	let index = ref(-1);
	let msgList = ref([]);
	let msgTotal = ref([]);

	let foot = ref(null);

	const popup = uni.getSubNVueById('chat-popup');

	const comEditorWidth = computed(() => editorWidth.value > 0 ? `width:${editorWidth.value}px;` : '');

	let currentInfo = computed(() => type.value === 'friend' ? contacts.friendMap[id.value] : contacts.groupMap[id.value]);

	let nameMap = computed(() => {
		if (type.value === 'friend') {
			return {
				[id.value]: info.value.nameRemark || info.value.friendName,
				[user.userId]: user.user.nickName,
			}
		} else {
			return contacts.groupUserMap[id.value].reduce((pre, v) => {
				if (v.uid == user.userId) {
					pre[v.uid] = user.user.nickName;
				} else if (contacts.frinedIdList.includes(v.uid)) {
					pre[v.uid] = contacts.friendMap[v.uid].nameRemark || v.nameRemark || v.nickName;
				} else {
					pre[v.uid] = v.nameRemark || v.nickName;
				}
				return pre;
			}, {});
		}
	});

	let avatarMap = computed(() => {
		if (type.value === 'friend') {
			return {
				[id.value]: info.value.headUrl,
				[user.userId]: user.user.avatarUrl,
			}
		} else {
			return contacts.groupUserMap[id.value].reduce((pre, v) => {
				if (v.uid == user.userId) {
					pre[v.uid] = user.user.avatarUrl;
				} else if (contacts.frinedIdList.includes(v.uid)) {
					pre[v.uid] = contacts.friendMap[v.uid].headUrl;
				} else {
					pre[v.uid] = v.headImg;
				}
				return pre;
			}, {});
		}
	});

	const computingTime = (time) => {
		if (dayjs().isSame(dayjs(time).format('YYYY-MM-DD'), 'date')) {
			return dayjs(time).format('Ah:mm');
		} else if (dayjs().isSame(dayjs(time).format('YYYY-MM-DD'), 'year')) {
			return dayjs(time).format('M月D日 Ah:mm');
		} else if (dayjs().isSame(dayjs(time).format('YYYY-MM-DD'), 'year')) {
			return dayjs(time).format('YYYY年M月D日 Ah:mm');
		}
	}

	let msgTime = computed(() => msgList.value.reduce((pre, v, i) => {
		if (i === 0) {
			pre[v.id] = computingTime(v.sendDateTimestamp);
		} else {
			let t = v.sendDateTimestamp - msgList.value[i - 1].sendDateTimestamp;
			pre[v.id] = t > 5 * 60 * 3000 ? computingTime(v.sendDateTimestamp) : 0;
		}
		return pre;
	}, {}));

	const onClickScroll = () => {
		// console.log('click');
		// uni.hideKeyboard();
	}

	const toUserInfo = (id) => {
		uni.navigateTo({
			url: `/pages/userInfo/userInfo?id=${id}`
		});
	}

	const onSendMsg = throttle(() => {
		if (type.value === 'friend') {
			socket.send({
				receive: id.value,
				info: msg.text,
				type: 1,
			});
		} else {
			let groupUsers = JSON.stringify(contacts.groupUserMap[id.value].filter(item => item.uid != user.userId)
				.map(item => item.uid));
			socket.send({
				groupId: id.value,
				groupUsers,
				info: msg.text,
				type: 2,
			});
		}
		editorCtx.value.clear();
	})

	const updateHeight = () => {
		const windowHeight = systemInfo.windowHeight;
		// 自动设置高度
		setTimeout(() => {
			uni.createSelectorQuery().select('#foot').boundingClientRect((res) => {
				chatViewHeight.value = windowHeight - Math.floor(res.height) - keyBoardHeight.value;
				scrollBottom();
			}).exec()
		}, 150);
	}

	const scrollBottom = () => {
		nextTick(() => {
			if (msgList.value.length === 0) return;
			intoView.value = intoView.value === 'chatId_' + msgList.value[msgList.value.length - 1].id ?
				'chatId_' + msgList.value[msgList.value.length - 2].id : 'chatId_' + msgList.value[msgList
					.value.length - 1].id;
		})
	}

	const onEditorReady = (e) => {
		uni.createSelectorQuery().select('#editor').context((res) => {
			editorCtx.value = res.context;
		}).exec()
	}

	const onEditorFocus = () => {
		showVoice.value = false;
		showEmoji.value = false;
		showMore.value = false;
	}

	const onEditorInput = throttle((e) => {
		msg.text = e.detail.text;
		msg.html = e.detail.html;
		msg.delta = e.detail.delta;
		updateHeight();
		if (e.detail.html === "<p><br></p>" || /^\n$/.test(e.detail.text)) {
			isMsg.value = false;
			editorWidth.value = 0;
		} else {
			if (isMsg.value) return;
			isMsg.value = true;
			setTimeout(() => {
				uni.createSelectorQuery().select('.send').boundingClientRect((res) => {
					editorWidth.value = uni.upx2px(750 - 200 - res.width * 2);
				}).exec()
			}, 50)
		}
	}, 500);

	const onStatusChange = (e) => {
		console.log(e);
	}

	const onShowVoice = () => {
		if (!showVoice.value) {
			showVoice.value = true;
			showEmoji.value = false;
			showMore.value = false;
			updateHeight();
		} else {
			showVoice.value = false;
			nextTick(() => {
				editorCtx.value.format('align', 'left');
			})
		}
	}

	const onShowEmoji = () => {
		if (!showEmoji.value) {
			setTimeout(() => {
				showEmoji.value = true;
			}, 100);
			showVoice.value = false;
			showMore.value = false;
			updateHeight();
		} else {
			showEmoji.value = false;
			nextTick(() => {
				editorCtx.value.format('align', 'left');
			})
		}
	}

	const onShowMore = () => {
		if (!showMore.value) {
			setTimeout(() => {
				showMore.value = true;
			}, 100);
			showVoice.value = false;
			showEmoji.value = false;
			updateHeight();
		} else {
			showMore.value = false;
			nextTick(() => {
				editorCtx.value.format('align', 'left');
			})
		}
	}

	const scrollToUpper = throttle((e) => {
		if (msgTotal.value.length > msgList.value.length) {
			let id = msgList.value[0].id;
			status.value = 'loading';
			msgList.value.splice(0, 0, ...msgTotal.value.slice(msgList.value.length, msgList.value.length + 20)
				.reverse());
			intoView.value = 'chatId_' + id;
			status.value = 'more';
		} else {
			status.value = 'noMore';
		}
	})

	const onEmoji = (e) => {
		editorCtx.value.insertText({
			text: e.emoji
		});
	}

	const msgLongPress = (msg) => {
		let width = 0;
		uni.createSelectorQuery().select('#w_' + msg.id).boundingClientRect((res) => {
			width = Math.round(res.width);
		}).exec();
		uni.createSelectorQuery().select('#msg_' + msg.id).boundingClientRect((res) => {
			let params = {};
			let isTop = true;
			let isLeft = true;

			if (msg.send == user.userId) {
				// right
				isLeft = false;
			} else {
				// left
				isLeft = true;
			}

			if (Math.round(res.top) < uni.upx2px(80 + 20)) {
				// bottom
				isTop = false;
				console.log(res);
				params.top = Math.round(res.bottom) + 44 + 'px';
			} else {
				// top
				isTop = true;
				params.top = Math.round(res.top) + 44 - uni.upx2px(80) - 5 + 'px';
			}

			uni.$emit('chat-data', {
				isTop,
				isLeft,
				msg,
				width,
				params,
			});
			popup.setStyle({
				"width": "100%",
				"height": systemInfo.windowHeight,
				'top': systemInfo.statusBarHeight,
			})
			popup.show('fade-in', 100, (e) => {});
		}).exec();
	}

	uni.onKeyboardHeightChange((e) => {
		keyBoardHeight.value = e.height > 0 ? e.height : 0;
		updateHeight();
	})

	uni.$on('chat-hide', () => {
		popup.hide('fade-out', 50);
	})

	// uni.$on('chat-event', (e) => {
	// 	switch (e) {
	// 		case 'copy':
	// 			uni.setClipboardData({
	// 				data: 'hello',
	// 				success: function() {
	// 					console.log('success');
	// 				}
	// 			});
	// 			break;
	// 		case 'withdraw':
	// 			break;
	// 		default:
	// 			break;
	// 	}
	// })

	uni.$on('receive-msg', (e) => {
		if (type.value === 'friend') {
			if (id.value == e.msg.send || id.value == e.msg.receive) {
				msgList.value.push(e.msg);
			} else {
				chatList[e.index].value.badge += 1;
			}
		} else {
			if (id.value == e.msg.groupId) {
				msgList.value.push(e.msg);
			} else {
				chatList[e.index].value.badge += 1;
			}
		}

		updateHeight();
	})

	onLoad((option) => {
		back.value = option.back;
		id.value = option.id;
		switch (option.type) {
			case 'friend':
				type.value = 'friend';
				info.value = contacts.friendMap[id.value];
				uni.setNavigationBarTitle({
					title: currentInfo.value.nameRemark || currentInfo.value.friendName
				});
				msgTotal.value = msgMap.value['friend_' + id.value] || [];
				if (msgTotal.value.length > 0) {
					msgList.value = msgTotal.value.slice(0, 20).reverse();
				}
				break;
			case 'group':
				type.value = 'group';
				info.value = contacts.groupMap[id.value];
				uni.setNavigationBarTitle({
					title: currentInfo.value.groupName +
						`(${Object.keys(contacts.groupUserMap[id.value]).length})`
				});
				msgTotal.value = msgMap.value['group_' + id.value] || [];
				if (msgTotal.value.length > 0) {
					msgList.value = msgTotal.value.slice(0, 20).reverse();
				}
				break;
			default:
				break;
		}

		chat.putChatList({
			type: type.value,
			id: id.value,
		});
		index.value = chatList.value.findIndex(item => item.type === type.value && item.id == id
			.value);
		chatList.value[index.value].badge = 0;

		updateHeight();
	});

	onBackPress((e) => {
		if (back.value === 'index') {
			uni.switchTab({
				url: '/pages/index/index'
			});
			return true;
		}

		if (type.value === 'friend') {
			uni.switchTab({
				url: '/pages/index/index'
			});
			return true;
		}
	});

	onNavigationBarButtonTap((e) => {
		switch (type.value) {
			case 'friend':
				uni.navigateTo({
					url: `/pages/chat/friendChatInfo?id=${id.value}`
				});
				break;
			case 'group':
				uni.navigateTo({
					url: `/pages/chat/groupChatInfo?id=${id.value}`
				});
				break;
			default:
				break;
		}
	})

	onUnload(() => {
		uni.$off('receive-msg');
		uni.$off('chat-hide');
		// uni.$off('chat-event');
	})
</script>

<style lang="scss">
	:deep(.ql-container) {
		box-sizing: border-box;
		border-radius: 10rpx;
		padding: 0 10rpx;
		font-size: 18px;
		background-color: #fff;
		height: auto;
		min-height: 40px;
		max-height: 180px;
	}

	:deep(.ql-container .ql-editor) {
		padding: 20rpx 0;
	}

	// text,
	// span,
	// p,
	// div {
	// 	user-select: all;
	// 	-webkit-user-select: all;
	// }
</style>

<style lang="scss" scoped>
	view {
		display: flex;
		flex-direction: column;
		box-sizing: border-box;
	}

	.chat {
		background-color: #ededed;
		padding-bottom: 50px;

		&-main {
			.chat-detail {
				width: 750rpx;
				margin: 10rpx 0;

				.time {
					width: 750rpx;
					height: 20px;
					margin: 10rpx 0;
					justify-content: center;
				}

				.text-msg {
					flex-direction: row;
				}

				.my {
					flex-direction: row-reverse;

					.chat-detail__main-name {
						align-items: flex-end;
					}
				}

				&__asdie {
					width: 120rpx;
					align-items: center;
				}

				&__main {
					max-width: 510rpx;
					padding-bottom: 20rpx;

					&-name {
						font-size: 12px;
					}

					&-info {
						padding: 20rpx;
						margin-top: 10rpx;
						border-radius: 6rpx;
						background-color: #fff;
						word-wrap: break-word;
						word-break: break-all;
						white-space: pre-line;
					}
				}
			}
		}
	}

	.foot {
		width: 750rpx;
		max-height: 750rpx;
		position: fixed;
		bottom: 0;
		z-index: 999;

		&__content {
			width: 750rpx;
			padding: 15rpx 20rpx;
			background-color: #f7f7f7;
			border-top: 1rpx solid #ceccca;
			flex-direction: row;
			align-items: flex-end;

			.icon_img {
				width: 50rpx;
				height: 50rpx;
			}

			&-left {
				margin-bottom: 10rpx;
			}

			&-center {
				flex: 1;
				padding: 0 20rpx;

				.textArea-box {}

				.voice_title {
					width: 500rpx;
					height: 42px;
					background-color: #fff;
					display: flex;
					justify-content: center;
					align-items: center;
				}
			}

			&-right {
				flex-direction: row;
				align-items: center;
				margin-bottom: 10rpx;
			}
		}
	}
</style>
